#include "Game.h"
#include "Player.h"
#include "expat.h"

/* This file contains Game methods that pertain to XML configuration.
   It uses two global friend functions and the passed user data to
   get back to the Game object */

#include <iostream>
#include <fstream>

using namespace std;

// TO DO: simple structure to hold a conference XML element and parser to
//        handle it - store levels in Game object

void
sm_xml_start(void *data, const char *el, const char **attr) {
  Game* pGame = (Game*)data;
  if(pGame) { pGame->xmlStart( el, attr ); }
}

void
sm_xml_end(void *data, const char *el) {
  Game* pGame = (Game*)data;
  if(pGame) { pGame->xmlEnd( el ); }
}

void Game::xmlStart( const char *el, const char **attr) {
  int i;

  // playerStart element
  if( !strcmp(el, "playerStart") ) {
    int x = PLAYER_POS_MIN_X;
    int y = PLAYER_POS_MIN_Y;
    sm_direction facing = sm_dir_none;
    for (i = 0; attr[i]; i += 2) {
      if( !strcmp(attr[i], "x") ) {
        x = atoi(attr[i+1]);
      }
      if( !strcmp(attr[i], "y") ) {
        y = atoi(attr[i+1]);
      }
      if( !strcmp(attr[i], "facing") ) {
        facing = (sm_direction)atoi(attr[i+1]);
      }

      if(x >= PLAYER_POS_MIN_X && x <= PLAYER_POS_MAX_X) {
        this->mpPlayer->posX = x; 
      }
      if(y >= PLAYER_POS_MIN_Y && y <= PLAYER_POS_MAX_Y) {
        this->mpPlayer->posY = y; 
      }
      if(facing >= sm_dir_up && facing <= sm_dir_left) {
        this->mpPlayer->Facing = facing; 
      }
      cout << " " << attr[i] << "='" << attr[i+1] << "'";
    }
  }
}  /* End of start handler */

void Game::xmlEnd( const char *el ) {
}  /* End of end handler */

void Game::InitConfig(const char* szConfigFilename)
{
  cout << "Opening config file '" << szConfigFilename << "'" << endl;

  XML_Parser p = XML_ParserCreate(NULL);
  if (! p) {
    fprintf(stderr, "Couldn't allocate memory for parser\n");
    exit(-1);
  }

  // set user-data pointer to this Game object
  XML_SetUserData(p, this);

  // read in the file into a buffer
  char* Buff = NULL;
  size_t size;
  ifstream file(szConfigFilename, ios::in|ios::ate);
  if(file.is_open())
  {
    size = file.tellg();
    Buff = new char[size];
    file.seekg(0, ios::beg);
    file.read(Buff, size);
    file.close();

    cout << "The complete config file content is in memory";
  }
  else {
    cout << "Unable to open config file";
    exit(1);
  }
  XML_SetElementHandler(p, sm_xml_start, sm_xml_end);

  for (;;) {
    int done;
    //int len;

    /*
    len = fread(Buff, 1, size, stdin);
    if (ferror(stdin)) {
      fprintf(stderr, "Read error\n");
      exit(-1);
    }
    done = feof(stdin);
    */

    if (! XML_Parse(p, Buff, size, 1)) {
      cerr << "Parse error at line " <<
	      XML_GetCurrentLineNumber(p) << ":" << endl <<
	      XML_ErrorString(XML_GetErrorCode(p)) << endl;
      exit(-1);
    }

    if (done)
      break;
  }

  cout << "Finished parsing config file" << endl;

  delete[] Buff;
}
